struct Ss {
    name: String,
    age: usize,
}

#[derive(Debug)]
struct Rectangle {
    width: i32,
    length: i32,
}

// impl 为实例定义方法  可以有多个impl
impl Rectangle {
    fn area(&self) -> i32 {
        self.length * self.width
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.length > other.length && self.width > other.width
    }

    // 关联函数
    fn square(size: i32) -> Rectangle {
        Rectangle {
            width: size,
            length: size,
        }
    }
}

// tuple struct
struct Color(i32, i32, i32);

fn main() {
    // struct
    // 实例要是可以变的，所有字段都是可变的，只有整体可变和整体不可变两种情况
    let sss = Ss {
        name: String::from("hello"),
        age: 12,
    };
    let mut s_mut = Ss {
        name: String::from("hello"),
        age: 12,
    };
    s_mut.name += "world";
    println!("不可变  {} | {}", sss.name, sss.age);
    println!("可变    {} | {}", s_mut.name, s_mut.age);
    // tuple struct 里面的元素没有名
    // 适用：想给整个tuple起名，并让它不同于其他的tuple，而且又不需要给每个元素起名
    let black = Color(0, 0, 0);

    // unit-Like Struct  没有任何字段
    // 需要在某个类型上实现某个trait，但是在里面又没有想要存储的数据

    //stuct 数据的所有权   只有struct实例是有效的，那么里面的字段都是有效的

    // 计算长方形的面积
    let rect = Rectangle {
        width: 30,
        length: 50,
    };

    let rect1 = Rectangle {
        width: 20,
        length: 40,
    };

    let rect2 = Rectangle {
        width: 35,
        length: 50,
    };

    println!("面积 {}", rect.area());

    println!("rect实例 {:?}", rect); // {:#?} 格式化输出\
    println!(" {rect:#?}"); // {:#?} 格式化输出

    // struct方法
    println!("面积 {}", area(&rect));
    println!("{}", rect.can_hold(&rect1)); 
    println!("{}", rect.can_hold(&rect2)); 

    // 关联函数  通常用于构造器(例子)
    // ::    -关联函数   -模块穿那件的命名空间

    let squ = Rectangle::square(32);
    println!("正方形 {:?}", squ); 
}

fn area(rect: &Rectangle) -> i32 {
    rect.length * rect.width
}
